package com.example.ftpfilesync.service;

import com.example.ftpfilesync.config.FtpProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class LocalFileService {

    private static final Logger logger = LoggerFactory.getLogger(LocalFileService.class);
    
    private final FtpProperties ftpProperties;

    public LocalFileService(FtpProperties ftpProperties) {
        this.ftpProperties = ftpProperties;
    }

    /**
     * 递归复制目录及其内容到本地路径
     *
     * @param sourcePath 源路径
     * @param targetPath 目标路径
     * @throws IOException IO异常
     */
    public void copyDirectory(String sourcePath, String targetPath) throws IOException {
        Path sourceDir = Paths.get(sourcePath);
        Path targetDir = Paths.get(targetPath);

        // 创建目标目录（包括所有必要的父目录）
        Files.createDirectories(targetDir);

        // 检查源目录是否存在
        if (!Files.exists(sourceDir)) {
            logger.warn("源目录不存在: {}", sourcePath);
            return;
        }

        // 复制目录
        List<String> copiedFiles = new ArrayList<>();
        copyRecursively(sourceDir, targetDir, copiedFiles);
        
        // 记录详细日志
        logger.info("目录 {} 同步完成，共处理 {} 个文件/子目录", sourcePath, copiedFiles.size());
        for (String copiedFile : copiedFiles) {
            logger.info("  已同步: {}", copiedFile);
        }
        
        // 如果需要保持时间戳一致，则复制源目录的时间戳到目标目录
        if (ftpProperties.isPreserveTimestamps()) {
            preserveTimestamps(sourceDir, targetDir);
        }
        
        logger.info("成功将目录 {} 复制到 {}", sourcePath, targetPath);
    }

    /**
     * 复制单个文件到本地路径
     *
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     * @throws IOException IO异常
     */
    public void copyFile(String sourcePath, String targetPath) throws IOException {
        Path sourceFile = Paths.get(sourcePath);
        Path targetFile = Paths.get(targetPath);

        // 创建目标文件的父目录（如果不存在）
        Path parentDir = targetFile.getParent();
        if (parentDir != null) {
            Files.createDirectories(parentDir);
        }

        // 检查源文件是否存在
        if (!Files.exists(sourceFile)) {
            logger.warn("源文件不存在: {}", sourcePath);
            return;
        }

        // 复制文件
        Files.copy(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING);
        
        // 如果需要保持时间戳一致，则复制源文件的时间戳到目标文件
        if (ftpProperties.isPreserveTimestamps()) {
            preserveTimestamps(sourceFile, targetFile);
        }
        
        logger.info("成功将文件 {} 复制到 {}", sourcePath, targetPath);
    }

    /**
     * 递归复制文件和目录
     *
     * @param source 源路径
     * @param target 目标路径
     * @param copiedFiles 已复制的文件列表
     * @throws IOException IO异常
     */
    private void copyRecursively(Path source, Path target, List<String> copiedFiles) throws IOException {
        if (Files.isDirectory(source)) {
            // 创建目标目录
            Files.createDirectories(target);
            copiedFiles.add("目录: " + source.toString() + " -> " + target.toString());
            
            // 遍历源目录中的所有文件和子目录
            Files.list(source).forEach(child -> {
                try {
                    Path targetChild = target.resolve(child.getFileName());
                    copyRecursively(child, targetChild, copiedFiles);
                    
                    // 如果需要保持时间戳一致，则复制源目录的时间戳到目标目录
                    if (ftpProperties.isPreserveTimestamps()) {
                        preserveTimestamps(child, targetChild);
                    }
                } catch (IOException e) {
                    logger.error("复制文件或目录时出错: {} -> {}", child, target, e);
                }
            });
        } else {
            // 复制文件
            Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
            copiedFiles.add("文件: " + source.toString() + " -> " + target.toString());
            logger.debug("已复制文件: {} -> {}", source, target);
            
            // 如果需要保持时间戳一致，则复制源文件的时间戳到目标文件
            if (ftpProperties.isPreserveTimestamps()) {
                preserveTimestamps(source, target);
            }
        }
    }

    /**
     * 保持源文件和目标文件的时间戳一致
     *
     * @param source 源文件路径
     * @param target 目标文件路径
     * @throws IOException IO异常
     */
    private void preserveTimestamps(Path source, Path target) throws IOException {
        // 获取源文件的时间戳
        FileTime lastModifiedTime = Files.getLastModifiedTime(source);
        
        // 设置目标文件的时间戳与源文件一致
        Files.setLastModifiedTime(target, lastModifiedTime);
        
        logger.debug("已保持时间戳一致: {} -> {}", source, target);
    }

    /**
     * 检查本地目录是否存在
     *
     * @param path 目录路径
     * @return true表示存在，false表示不存在
     */
    public boolean directoryExists(String path) {
        return Files.exists(Paths.get(path));
    }

    /**
     * 创建本地目录（包括所有必要的父目录）
     *
     * @param path 目录路径
     * @throws IOException IO异常
     */
    public void createDirectory(String path) throws IOException {
        Files.createDirectories(Paths.get(path));
    }
}